// 云对象教程: https://uniapp.dcloud.net.cn/uniCloud/cloud-obj
// jsdoc语法提示教程：https://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/129
module.exports = {
	_before: function() { // 通用预处理器

	},
	/**
	 * method1方法描述
	 * @param {string} param1 参数1描述
	 * @returns {object} 返回值描述
	 */
	/*
	method1(param1) {
	    // 参数校验，如无参数则不需要
	    if (!param1) {
	        return {
	            errCode: 'PARAM_IS_NULL',
	            errMsg: '参数不能为空'
	        }
	    }
	    // 业务逻辑

	    // 返回结果
	    return {
	        param1 //请根据实际需要返回值
	    }
	}
	*/

	// 获取远程景点列表
	async updateViewSpotData() {
		const db = uniCloud.database();
		const collection = db.collection('view_spot');

		// 获取景点列表
		let apiUrl = 'https://card.ly3618.com/jxcard/api/card/v1/cardViewspot/listShowPage';
		let request_data = {
			"ifshow": '1',
			"orderName": "px",
			"orderType": "asc",
			"page": "1",
			"size": "200",
			"tag": "5107",
		};
		const res = await uniCloud.httpclient.request(apiUrl, {
			method: 'POST',
			data: request_data,
			contentType: 'json',
			dataType: 'json'
		})
		if (res.data.code != 200) {
			return {
				"code": 0,
				"msg": "获取数据失败",
				"data": [],
			};
		}

		// 清理全部数据
		const dbCmd = db.command
		await collection.where({
			_id: dbCmd.neq(null)
		}).remove()

		const now = new Date();

		// 插入数据
		let saveData = res.data.data;
		saveData.forEach(function(item, index) {
			let point = bMapToQQMap(item.lng, item.lat)
			saveData[index].lng = point.lng
			saveData[index].lat = point.lat
			saveData[index].point = new db.Geo.Point(Number(point.lng), Number(point.lat));
			saveData[index].lastUpdated = now;
		});
		await collection.add(saveData)
		return {
			"code": 1,
			"msg": "已更新最新数据",
			"data": [],
		};
	},

	// 列表
	async getViewSpotList(keyword = '', lng = '', lat = '') {
		const db = uniCloud.database();
		const collection = db.collection('view_spot');

		/* // 获取最后更新时间
		const lastUpdatedRes = await collection.orderBy('last_updated', 'desc').limit(1).get();
		const lastUpdated = lastUpdatedRes.data[0]?.last_updated || null;

		// 设置缓存时间阈值（例如，1小时）
		const CACHE_THRESHOLD = 3600 * 2000; // 2小时
		const now = new Date();

		// 如果超过阈值，更新数据
		if (!lastUpdated || (now.getTime() - lastUpdated.getTime()) > CACHE_THRESHOLD) {
			updateViewSpotDataFunction();
		} */

		// 搜索条件
		let map = {};
		if (keyword) {
			map.name = new RegExp(keyword)
		}
		if (lng && lat) {
			map.point = db.command.geoNear({
				geometry: new db.Geo.Point(lng, lat),
				maxDistance: 10000000,
				minDistance: 0
			})
		}

		let res = await collection.where(map).get()
		let data = res.data;

		data.forEach(function(item, index) {
			data[index].distance = lng && lat ? haversineGreatCircleDistance(lat, lng, item.lat, item.lng) : 0;
		})
		return {
			"code": 1,
			"msg": "操作成功",
			"data": data,
		};
	},

	// 详情
	async getViewSpotInfo(id = 0, lng = '', lat = '') {
		const db = uniCloud.database();

		let res = await db.collection('view_spot').where({
			id: id * 1
		}).get()

		let data = res.data[0];
		data.distance = lng && lat ? haversineGreatCircleDistance(lat, lng, data.lat, data.lng) : 0;

		return {
			"code": 1,
			"msg": "操作成功",
			"data": data,
		};
	}
}

const R = 6371;

function haversineGreatCircleDistance(lat1, lon1, lat2, lon2) {
	// 将十进制度数转化为弧度
	const latDistance = toRadians(lat2 - lat1);
	const lonDistance = toRadians(lon2 - lon1);
	lat1 = toRadians(lat1);
	lat2 = toRadians(lat2);

	// 应用haversine公式
	const a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2) +
		Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2) * Math.cos(lat1) * Math.cos(lat2);
	const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

	// 返回距离（单位：公里）
	return (R * c).toFixed(2) + 'km';
}

function toRadians(angle) {
	return angle * (Math.PI / 180);
}

function bMapToQQMap(lng, lat) {
	if (lng == null || lng == '' || lat == null || lat == '')
		return [lng, lat];

	var x_pi = 3.14159265358979324;
	var x = parseFloat(lng) - 0.0065;
	var y = parseFloat(lat) - 0.006;
	var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
	var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
	var lng = (z * Math.cos(theta)).toFixed(7);
	var lat = (z * Math.sin(theta)).toFixed(7);

	return {
		lng: lng,
		lat: lat,
	};
}